{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 载入数据\n",
    "data = np.genfromtxt(\"kmeans.txt\", delimiter=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 计算距离 \n",
    "def euclDistance(vector1, vector2):  \n",
    "    return np.sqrt(sum((vector2 - vector1)**2))\n",
    "  \n",
    "# 初始化质心\n",
    "def initCentroids(data, k):  \n",
    "    numSamples, dim = data.shape\n",
    "    # k个质心，列数跟样本的列数一样\n",
    "    centroids = np.zeros((k, dim))  \n",
    "    # 随机选出k个质心\n",
    "    for i in range(k):  \n",
    "        # 随机选取一个样本的索引\n",
    "        index = int(np.random.uniform(0, numSamples))  \n",
    "        # 作为初始化的质心\n",
    "        centroids[i, :] = data[index, :]  \n",
    "    return centroids  \n",
    "  \n",
    "# 传入数据集和k的值\n",
    "def kmeans(data, k):  \n",
    "    # 计算样本个数\n",
    "    numSamples = data.shape[0]   \n",
    "    # 样本的属性，第一列保存该样本属于哪个簇，第二列保存该样本跟它所属簇的误差\n",
    "    clusterData = np.array(np.zeros((numSamples, 2)))  \n",
    "    # 决定质心是否要改变的变量\n",
    "    clusterChanged = True  \n",
    "  \n",
    "    # 初始化质心  \n",
    "    centroids = initCentroids(data, k)  \n",
    "  \n",
    "    while clusterChanged:  \n",
    "        clusterChanged = False  \n",
    "        # 循环每一个样本 \n",
    "        for i in range(numSamples):  \n",
    "            # 最小距离\n",
    "            minDist  = 100000.0  \n",
    "            # 定义样本所属的簇\n",
    "            minIndex = 0  \n",
    "            # 循环计算每一个质心与该样本的距离\n",
    "            for j in range(k):  \n",
    "                # 循环每一个质心和样本，计算距离\n",
    "                distance = euclDistance(centroids[j, :], data[i, :])  \n",
    "                # 如果计算的距离小于最小距离，则更新最小距离\n",
    "                if distance < minDist:  \n",
    "                    minDist  = distance  \n",
    "                    # 更新样本所属的簇\n",
    "                    minIndex = j  \n",
    "                    # 更新最小距离\n",
    "                    clusterData[i, 1] = distance\n",
    "              \n",
    "            # 如果样本的所属的簇发生了变化\n",
    "            if clusterData[i, 0] != minIndex:  \n",
    "                # 质心要重新计算\n",
    "                clusterChanged = True\n",
    "                # 更新样本的簇\n",
    "                clusterData[i, 0] = minIndex\n",
    "  \n",
    "        # 更新质心\n",
    "        for j in range(k):  \n",
    "            # 获取第j个簇所有的样本所在的索引\n",
    "            cluster_index = np.nonzero(clusterData[:, 0] == j)\n",
    "            # 第j个簇所有的样本点\n",
    "            pointsInCluster = data[cluster_index]  \n",
    "            # 计算质心\n",
    "            centroids[j, :] = np.mean(pointsInCluster, axis = 0) \n",
    "#         showCluster(data, k, centroids, clusterData)\n",
    " \n",
    "    return centroids, clusterData  \n",
    "  \n",
    "# 显示结果 \n",
    "def showCluster(data, k, centroids, clusterData):  \n",
    "    numSamples, dim = data.shape  \n",
    "    if dim != 2:  \n",
    "        print(\"dimension of your data is not 2!\")  \n",
    "        return 1  \n",
    "  \n",
    "    # 用不同颜色形状来表示各个类别\n",
    "    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']  \n",
    "    if k > len(mark):  \n",
    "        print(\"Your k is too large!\")  \n",
    "        return 1  \n",
    "  \n",
    "    # 画样本点  \n",
    "    for i in range(numSamples):  \n",
    "        markIndex = int(clusterData[i, 0])  \n",
    "        plt.plot(data[i, 0], data[i, 1], mark[markIndex])  \n",
    "  \n",
    "    # 用不同颜色形状来表示各个类别\n",
    "    mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']  \n",
    "    # 画质心点 \n",
    "    for i in range(k):  \n",
    "        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)  \n",
    "  \n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "F:\\Anaconda3\\lib\\site-packages\\numpy\\core\\fromnumeric.py:2957: RuntimeWarning: Mean of empty slice.\n",
      "  out=out, **kwargs)\n",
      "F:\\Anaconda3\\lib\\site-packages\\numpy\\core\\_methods.py:73: RuntimeWarning: invalid value encountered in true_divide\n",
      "  ret, rcount, out=ret, casting='unsafe', subok=False)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cluster complete!\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nlQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21e0a940978>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 设置k值\n",
    "k = 4  \n",
    "# centroids 簇的中心点 \n",
    "# cluster Data样本的属性，第一列保存该样本属于哪个簇，第二列保存该样本跟它所属簇的误差\n",
    "centroids, clusterData = kmeans(data, k)  \n",
    "print('cluster complete!')   \n",
    "# 显示结果\n",
    "showCluster(data, k, centroids, clusterData)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 做预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1],\n",
       "       [0, 1]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 做预测\n",
    "x_test = [0,1]\n",
    "np.tile(x_test,(k,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2.46154315, -1.78737555],\n",
       "       [ 3.01169468,  4.01238673],\n",
       "       [-2.82102866,  0.60870808],\n",
       "       [        nan,         nan]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差\n",
    "np.tile(x_test,(k,1))-centroids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 6.05919468,  3.19471136],\n",
       "       [ 9.07030486, 16.09924725],\n",
       "       [ 7.95820269,  0.37052553],\n",
       "       [        nan,         nan]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差平方\n",
    "(np.tile(x_test,(k,1))-centroids)**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 9.25390604, 25.16955211,  8.32872821,         nan])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 误差平方和\n",
    "((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 最小值所在的索引号\n",
    "np.argmin(((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def predict(datas):\n",
    "    return np.array([np.argmin(((np.tile(data,(k,1))-centroids)**2).sum(axis=1)) for data in datas])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 画出簇的作用区域"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21e02274ac8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 获取数据值所在的范围\n",
    "x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1\n",
    "y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1\n",
    "\n",
    "# 生成网格矩阵\n",
    "xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),\n",
    "                     np.arange(y_min, y_max, 0.02))\n",
    "\n",
    "z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似，多维数据转一维。flatten不会改变原始数据，ravel会改变原始数据\n",
    "z = z.reshape(xx.shape)\n",
    "# 等高线图\n",
    "cs = plt.contourf(xx, yy, z)\n",
    "# 显示结果\n",
    "showCluster(data, k, centroids, clusterData)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
